package cn.maidouya.hrm.controller;

import cn.maidouya.hrm.config.HighlightResultMapper;
import cn.maidouya.hrm.doc.CourseDoc;
import cn.maidouya.hrm.query.CourseDocQuery;
import cn.maidouya.hrm.repository.CourseDocRepository;
import cn.maidouya.hrm.util.AjaxResult;
import cn.maidouya.hrm.vo.Aggvo;
import cn.maidouya.hrm.vo.PageList;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.StringTerms;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import javax.swing.*;
import java.util.*;

@RestController
@RequestMapping("/courseDoc")
public class CourseDocController {
    @Autowired // 通过feign获取注解对象
    private CourseDocRepository courseDocRepository;
    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;
    @Autowired
    private HighlightResultMapper highlightResultMapper;
    @PostMapping("/onLine")
    @PreAuthorize("hasAuthority('courseDoc:add')")
    public AjaxResult onLineCourse(@RequestBody List<CourseDoc> courseDoc) {
        courseDocRepository.saveAll(courseDoc);
        return AjaxResult.me();
    }
    @PostMapping("/offLine")
    public AjaxResult offLineCourse(@RequestBody List<Long> ids) {
            ids.forEach(e->{
                courseDocRepository.deleteById(e);
            });
        return AjaxResult.me();
    }

    @PostMapping("/queryCourses")
    public AjaxResult queryCourses(@RequestBody CourseDocQuery courseDocQuery){
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
       // elasticsearch中Sql执行方法对象
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();

        // 一、关键词搜索
                String keyword = courseDocQuery.getKeyword();
                if (StringUtils.isNotBlank(keyword)){
                    // 1. 搜索单个条件
                  // boolQueryBuilder.must(QueryBuilders.matchQuery("name",keyword));
                    // 2. 搜索多个条件
                    boolQueryBuilder.must(QueryBuilders.multiMatchQuery(keyword,"name","tenantName"));
            }
        // 二、价格     范围过滤  注意：ES中Sql格式
                 Float priceMax = courseDocQuery.getPriceMax();
                // 1. 较空 ES中字段price价格小于前端参数值priceMax    注意：价格大小于 否则展示不出来
                if (priceMax != null){
                    boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").lte(priceMax));
                }
                // 2. 较空 ES中字段price价格大于前端参数值priceMin
                Float priceMin = courseDocQuery.getPriceMin();
                if (priceMin != null){
                    boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").gte(priceMin));
                }

        //  聚合关键词查询
                Long courseTypeId = courseDocQuery.getCourseTypeId();
                if (courseTypeId != null){
                    boolQueryBuilder.filter(QueryBuilders.termQuery("courseTypeId",courseTypeId));
                }
                String courseTypeName = courseDocQuery.getCourseTypeName();
                if (StringUtils.isNotBlank(courseTypeName)){
                    boolQueryBuilder.filter(QueryBuilders.termQuery("courseTypeName",courseTypeName));
                }


        builder.withQuery(boolQueryBuilder);
        // 三、排序
                // 1. 关键词排序 sortField没有值或者空串就按照价格排序 sortField
                String sortField = courseDocQuery.getSortField();
                sortField =  (sortField == null || sortField.trim().equals("")) ? "price" : sortField;
                // 2. 关键词排序升序或者降序
                String sortType = courseDocQuery.getSortType();
                SortOrder type = sortType == null || SortOrder.DESC.toString().equals(sortType) ? SortOrder.DESC : SortOrder.ASC;
                // 3. 执行排序条件
                FieldSortBuilder fieldSortBuilder = new FieldSortBuilder(sortField);
                // 4. 调用升降序方法
                fieldSortBuilder.order(type);
                // 5. 执行监听排序
                builder.withSort(fieldSortBuilder);
        //  聚合关键词
            builder.addAggregation(AggregationBuilders.terms("tenantNameAgg").field("tenantName").order(Terms.Order.count(false)).size(20));
            builder.addAggregation(AggregationBuilders.terms("courseTypeAgg").field("courseTypeName").order(Terms.Order.count(false)).size(20));

        // 1. 分页
                PageRequest pageRequest = new PageRequest(courseDocQuery.getPage()-1, courseDocQuery.getRows());
                builder.withPageable(pageRequest);
        // 高亮
            // 设置高亮显示
           if (courseDocQuery.getHighlight() == 1){
               HighlightBuilder.Field field = new HighlightBuilder.Field("name").preTags("<font style='color:red'><b>").postTags("</b></font>");
               builder.withHighlightFields(field);  // 名字高亮
           }
        // courseDocRepository不支持高亮
        // Page<CourseDoc> search = courseDocRepository.search(builder.build());
        AggregatedPage<CourseDoc> search = elasticsearchTemplate.queryForPage(builder.build(), CourseDoc.class, highlightResultMapper);

        // 聚合关键词结果封装
            StringTerms tenanTerms = (StringTerms) search.getAggregation("tenantNameAgg");
            List<Aggvo> tenantList = new ArrayList<>();
            List<StringTerms.Bucket> tenantNameAgg = tenanTerms.getBuckets();
            tenantNameAgg.stream().forEach(bucket -> {
                String key = bucket.getKeyAsString();
                long count = bucket.getDocCount();
                Aggvo aggvo = new Aggvo();
                aggvo.setName(key);
                aggvo.setCount(count);
                tenantList.add(aggvo);
            });
        StringTerms courseTerms = (StringTerms)search.getAggregation("courseTypeAgg");
        ArrayList<Aggvo> courseList = new ArrayList<>();
        List<StringTerms.Bucket> courseAgg = courseTerms.getBuckets();
        courseAgg.stream().forEach(bucket -> {
            Aggvo aggvo = new Aggvo();
            String key = bucket.getKeyAsString();
            long count = bucket.getDocCount();
            aggvo.setName(key);
            aggvo.setCount(count);
            courseList.add(aggvo);
        });
        // 聚合封装list对象
            HashMap<String, List<Aggvo>> map = new HashMap<String, List<Aggvo>>();
            map.put("tenantList",tenantList);
            map.put("courseList",courseList);
        // 返回数据首页
        return AjaxResult.me().setResultObj(new PageList<CourseDoc>(search.getTotalElements(),search.getContent(), map));
    }

}